package hn.cch.quartz;

import hn.cch.quartz.job.QuartzJob;
import hn.cch.util.DateUtil;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import java.util.Date;

@Scope(value = "singleton")
@Component
public class QuartzJobManager {


    private static final Logger logger = LoggerFactory.getLogger(QuartzJobManager.class);

    @Autowired
    private Scheduler scheduler;

    public void initJob() {
        boolean flag0 = initQuartzJob();
        if (!flag0) {
            System.exit(-1);
        }

    }

    private boolean initQuartzJob() {

        String jobName = "Quartz_Job";
        String jobGroup = "Spring_Dao";
        try {
            JobKey jobKey = new JobKey(jobName, jobGroup);
            JobDetail jobDetail = JobBuilder.newJob(QuartzJob.class)
                    .withIdentity(jobKey).storeDurably().build();
            TriggerKey triggerKey = new TriggerKey(jobName, jobGroup);
            CronTrigger cronTrigger = TriggerBuilder.newTrigger()
                    .forJob(jobKey).withIdentity(triggerKey)
                    .withSchedule(CronScheduleBuilder.cronSchedule("00 * * * * ?"))
                    .build();



            Date date = scheduler.scheduleJob(jobDetail, cronTrigger);
            logger.info("first:{}", date);
            return true;
        } catch (Exception e) {
            logger.error("error:{}", e.getMessage());
            return false;
        }

    }

    public boolean scheduleJob() {

        String jobName = "Quartz_Job";
        String jobGroup = "Spring_Dao";
        try {

            Date startDate = DateUtil.changeDate(new Date(), 1, 5);//5秒后执行

            JobKey jobKey = new JobKey(jobName, jobGroup);
            JobDetail jobDetail = JobBuilder.newJob(QuartzJob.class)
                    .withIdentity(jobKey).storeDurably().build();
            TriggerKey triggerKey = new TriggerKey(jobName, jobGroup);
            SimpleTrigger simpleTrigger = TriggerBuilder.newTrigger()
                    .forJob(jobKey).withIdentity(triggerKey)
                    .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                            .withRepeatCount(1).withIntervalInSeconds(1))
                    .startAt(startDate).build();//设置开始时间



            Date date = scheduler.scheduleJob(jobDetail, simpleTrigger);
            if (date != null) {
                logger.info(jobName + "_first_date:" + date.toString());
                return true;
            } else {
                logger.error(jobName + " schedule failed");
                return false;
            }
        } catch (SchedulerException e) {
            logger.error(e.getMessage());
            return false;
        }
    }

    public boolean rescheduleJob() {

        String jobName = "Quartz_Job";
        String jobGroup = "Spring_Dao";
        try {


            Date startDate = DateUtil.changeDate(new Date(), 1, 5);//5秒后执行
            JobKey jobKey = new JobKey(jobName, jobGroup);
            TriggerKey triggerKey = new TriggerKey(jobName, jobGroup);
            SimpleTrigger newTrigger = TriggerBuilder.newTrigger()
                    .forJob(jobKey).withIdentity(triggerKey)
                    .withSchedule(SimpleScheduleBuilder.simpleSchedule())
                    .startAt(startDate).build();//设置开始时间

            /**
             *
             * 前提说明：
             * jobDetail和trigger都要使用withIdentity方法配置jobName和jobGroup
             * 使用说明：
             * 1.当jobDetail不存在时scheduleJob和rescheduleJob都失败（抛异常）
             * 需要给jobDetail配置持久化（storeDurably方法）
             * 否则当trigger不在触发失效后与之绑定的jobDetail会被一起清理
             *
             * 2.当oldTrigger不存在时reschedule会失败，返回firstFireDate为null
             * JobrescheduleJob获取不到以前的触发器，也就无法替换新的触发器，
             * 这时应该使用scheduleJob重新绑定新的触发器
             * 如果scheduleJob返回返回firstFireDate也为null，说明前提条件不满足
             *
             *
             */
            JobDetail jobDetail = scheduler.getJobDetail(jobKey);
            if (jobDetail == null){
                logger.error(jobName + " not exist");
                return false;
            }
            Trigger oldTrigger = scheduler.getTrigger(triggerKey);
            if (oldTrigger == null){
                Date date = scheduler.scheduleJob(newTrigger);
                if (date != null) {
                    logger.info(jobName + "_schedule_date:" + date.toString());
                    return true;
                } else {
                    logger.error(jobName  + " schedule failed");
                    return false;
                }
            }else {
                Date date = scheduler.rescheduleJob(triggerKey, newTrigger);
                if (date != null) {
                    logger.info(jobName + "_reschedule_date:" + date.toString());
                    return true;
                } else {
                    logger.error(jobName + " reschedule failed");
                    return false;
                }
            }
        } catch (SchedulerException e) {
            logger.error(e.getMessage());
            return false;
        }
    }

}
